home *** CD-ROM | disk | FTP | other *** search
- *
- * $VER: asin.s 33.1 (22.1.97)
- *
- * Calculates the arcsine of the source
- *
- * Version history:
- *
- * 33.1 22.1.97 (c) Motorola
- *
- * - snipped from M68060SP sources
- *
-
- machine 68040
- fpu 1
-
- XDEF _asin
- XDEF @asin
-
- XREF @atan
-
- *************************************************************************
- * asin(): computes the inverse sine of a normalized input *
- * *
- * INPUT *************************************************************** *
- * fp0 = extended precision input *
- * *
- * OUTPUT ************************************************************** *
- * fp0 = arcsin(X) *
- * *
- * ACCURACY and MONOTONICITY ******************************************* *
- * The returned result is within 3 ulps in 64 significant bit, *
- * i.e. within 0.5001 ulp to 53 bits if the result is subsequently *
- * rounded to double precision. The result is provably monotonic *
- * in double precision. *
- * *
- * ALGORITHM *********************************************************** *
- * *
- * ASIN *
- * 1. If |X| >= 1, go to 3. *
- * *
- * 2. (|X| < 1) Calculate asin(X) by *
- * z := sqrt( [1-X][1+X] ) *
- * asin(X) = atan( x / z ). *
- * Exit. *
- * *
- * 3. If |X| > 1, go to 5. *
- * *
- * 4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.*
- * *
- * 5. (|X| > 1) Generate an invalid operation by 0 * infinity. *
- * Exit. *
- * *
- *************************************************************************
-
- PIBY2 dc.l $3FFF0000,$C90FDAA2,$2168C235,$00000000
-
- _asin
- fmove.d (4,sp),fp0
- @asin
- fmove.x fp0,-(sp)
-
- move.l (sp),d1
- move.w (4,sp),d1
- and.l #$7FFFFFFF,d1
- cmp.l #$3FFF8000,d1
- bge.b .ASINBIG
-
- ; This catch is added here for the '060 QSP. Originally, the call to
- ; satan() would handle this case by causing the exception which would
- ; not be caught until gen_except(). Now, with the exceptions being
- ; detected inside of satan(), the exception would have been handled there
- ; instead of inside sasin() as expected.
- cmp.l #$3FD78000,d1
- blt.w .ASINTINY
-
- ;--THIS IS THE USUAL CASE, |X| < 1
- ;--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
-
- .ASINMAIN
- lea (12,sp),sp
- fmove.s #$3F800000,fp1
- fsub.x fp0,fp1 ; 1-X
- fmovem.x fp2,-(sp) ; {fp2}
- fmove.s #$3F800000,fp2
- fadd.x fp0,fp2 ; 1+X
- fmul.x fp2,fp1 ; (1+X)(1-X)
- fmovem.x (sp)+,fp2 ; {fp2}
- fsqrt.x fp1 ; SQRT([1-X][1+X])
- fdiv.x fp1,fp0 ; X/SQRT([1-X][1+X])
- jsr @atan
- rts
-
- .ASINBIG
- fabs.x fp0 ; |X|
- fcmp.s #$3F800000,fp0
- fbgt .operr ; cause an operr exception
-
- ;--|X| = 1, ASIN(X) = +- PI/2.
- .ASINONE
- fmove.x (PIBY2,pc),fp0
- move.l (sp),d1
- and.l #$80000000,d1 ; SIGN BIT OF X
- lea (12,sp),sp
- or.l #$3F800000,d1 ; +-1 IN SGL FORMAT
- move.l d1,-(sp) ; push SIGN(X) IN SGL-FMT
- fmul.s (sp)+,fp0
- rts
-
- ;--|X| < 2^(-40), ATAN(X) = X
- .ASINTINY
- .operr
- lea (12,sp),sp
- rts
-